home *** CD-ROM | disk | FTP | other *** search
- {
- File: UDialogUtils.p
-
- Contains: This unit is an embryonic version of an alternative to the Dialog Manager.
- Why replace the Dialog Manager? For dialogs with just a few basic items like
- some static text and some buttons, the Dialog Manager isn’t too bad. It still
- doesn’t handle low-memory situations at all well nor does it handle cases in
- which some resources are missing with much grace, but a small dialog shouldn’t
- have too many problems with low-memory situations and clever memory
- management can avoid all problems, and missing resources is an anomalous
- situation. The Dialog Manager exposes its problems once a dialog starts to
- get a bit complicated. User items and controls become difficult to manage,
- and even something as simple as a static text item that’s in a different size
- or style becomes a major hassle to implement. The ictb mechanism introduced
- on Color QuickDraw machines was supposed to make it easier to specify static
- and edit text styles, but this mechanism is so buggy that it’s useless in my
- opinion. Another problem with the Dialog Manager is its slow performance when
- drawing items. Technical Note #203 “Don’t Abuse the Managers” has many words
- of wisdom when it comes to the Dialog Manager, like don’t use it.
-
- Of course, the usual reply we get to this is, “But ResEdit’s DITL editor makes
- arranging dialogs so easy!” This is true, and I think it’s a compelling
- argument. This also makes localization very easy, which isn’t a trivial
- concern. But who said that only the Dialog Manager can read DITLs? The
- structure of a DITL is very well-defined, and couldn’t possibly change without
- breaking every program that put up an alert box. DITL resources aren’t that
- complicated, and your own program can read them as well as the Dialog
- Manager——better probably.
-
- That’s what this unit does. It reads in a DITL, creates an internal item list
- based on what it found in the DITL, then attaches this item list to the
- "items" field of a DialogRecord. This unit also contains routines to draw the
- items and routines to set static text items. And it does this while checking
- for errors; what a concept!
-
- But, as I said, this unit is very embryonic. The first time I tried this, I
- made it very complete, but I also made it much, much harder to use than the
- Dialog Manager. So, I almost completely stripped it for the purposes of this
- sample application. Now, it only handles static text items and buttons, and
- it no longer handles modal dialogs. Eventually, I want to give this the full
- functionality of the real Dialog Manager.
-
- One capability this unit has that the Dialog Manager doesn’t implement is
- style information for static text items. I don’t mean one static text item
- with multiple text styles. I mean different items can have different text
- styles. Doing this through the Dialog Manager involves much more work than
- it should. The way I do this while keeping the DITL structure is to use the
- four bytes used for a placeholder for handle or procedure pointer in Inside
- Macintosh I page 427. If you want static text items displayed in the standard
- font, style, and justification, then just leave these four bytes set to 0. If
- you want to specify the type face, style, size, and line justification, then
- each of these four bytes can hold each of these pieces of information.
-
- The first byte holds a font index. This isn’t a font number because, as
- Technical Note #191 “Font Names” says, it isn’t nice to save font numbers.
- This font index is an index into a STR# resource which contains the names of
- whatever fonts you want to use in this dialog. For example, if the second
- string in the STR# resource is "Monaco", then a 2 placed into the font index
- field will cause the DrawDialogItems routine defined in this unit to display
- that static text item in Monaco. The STR# resource should have a resource ID
- of 0. This lets all dialog boxes use the same font list. You can override
- this font list by specifying a STR# resource with an ID equal to the resource
- ID of the DITL being read. In this way, you can provide a STR# resource ID 0
- that contains the default font list, and then provide special font lists for
- for specific DITLs.
-
- The second byte holds the style (“face” according to QuickDraw) of the static
- text item. This holds the same value as the Style type. The third byte
- contains the point size of the static text. The point size is limited to 255,
- which shouldn’t be a problem. The last byte contains the justification of the
- static text. -2 means left justification, -1 means right justification, 0
- means default justification, and 1 means center justification.
-
- Written by: Forrest Tanaka
-
- Copyright: Copyright © 1988-1999 by Apple Computer, Inc., All Rights Reserved.
-
- You may incorporate this Apple sample source code into your program(s) without
- restriction. This Apple sample source code has been provided "AS IS" and the
- responsibility for its operation is yours. You are not permitted to redistribute
- this Apple sample source code as "Apple sample source code" after having made
- changes. If you're going to re-distribute the source, we require that you make
- it clear in the source that the code was descended from Apple sample source
- code, but that you've made changes.
-
- Change History (most recent first):
- 7/27/1999 Karl Groethe Updated for Metrowerks Codewarror Pro 2.1
-
-
- }
- UNIT UDialogUtils;
-
- {[j=20/57/1$] Pasmat Options}
-
-
- INTERFACE
-
- USES
- Dialogs
- ;
-
- (*******************************************************************************
- * Used Units
- *******************************************************************************)
-
- (*******************************************************************************
- * Constants
- *******************************************************************************)
-
- CONST
- kNoItem = -1; {No dialog item is applicable or end of dialog item list}
-
-
- (*******************************************************************************
- * Types
- *******************************************************************************)
-
- TYPE
- (* Type information for static text items *)
- TypeInfoRec = RECORD
- typeFace: Integer; {Font number of text}
- typeSize: Integer; {Font size of text}
- textJust: Integer; {Justification of text}
- typeStyle: Style; {Font style of text}
- END;
-
-
- (*******************************************************************************
- * InstallDialogItems - Install a DITL into a dialog window
- *
- * This routine is called to install a DITL into the dialog window specified by
- * "aDialog". The resource ID of the desired DITL is specified by "itemListNum".
- * InstallDialogItems returns noErr if the item list was successfully created and
- * attached to aDialog, otherwise, an operating system error code is returned.
- *******************************************************************************)
-
- FUNCTION InstallDialogItems (aDialog: DialogPtr;
- itemListNum: Integer): OSErr;
-
-
- (*******************************************************************************
- * SetStatTextItem - Set a static text dialog item to the specified text
- *
- * This routine sets the text of a static text item to the text pointed to by
- * "textPtr" and having the length "textLength". "aDialog" is a pointer to the
- * dialog box that this is being done in, and "itemNum" is the item number of the
- * static text item to set. If that item isn’t actually a static text item, then
- * nothing is done. If there isn’t enough memory to put the text into the static
- * text item, then nothing is done.
- *******************************************************************************)
-
- PROCEDURE SetStatTextItem (aDialog: DialogPtr;
- itemNum: Integer;
- textPtr: Ptr;
- textLength: Integer);
-
-
- (*******************************************************************************
- * GetStatTextFontInfo - Get font information for a static text item
- *
- * This routine gets the font information for the static text item with an item
- * number of "itemNum" in the dialog specified by "aDialog". This font
- * information is returned in "typeInfo". The the specified item isn’t a static
- * text item, then nothing is done.
- *******************************************************************************)
-
- PROCEDURE GetStatTextFontInfo (aDialog: DialogPtr;
- itemNum: Integer;
- VAR typeInfo: TypeInfoRec);
-
-
- (*******************************************************************************
- * DrawDialogItems - Draw all standard dialog items
- *
- * All standard dialog items in the dialog box pointed to by "aDialog" are drawn.
- *******************************************************************************)
-
- PROCEDURE DrawDialogItems (aDialog: DialogPtr);
-
-
- (*******************************************************************************
- * GetDialogItemRect - Get the item rectangle of a specified dialog item
- *
- * This routine gets the item rectangle of the dialog item in the dialog box
- * specified by "aDialog" and having an item number of "itemNum". This rectangle
- * is returned in "itemRect".
- *******************************************************************************)
-
- PROCEDURE GetDialogItemRect (aDialog: DialogPtr;
- itemNum: Integer;
- VAR itemRect: Rect);
-
-
- (*******************************************************************************
- * DisposeDialogItems - Dispose of all dialog items in the specified dialog box
- *
- * This routine disposes of the memory used by all the dialog items in the dialog
- * box specified by "aDialog". The item list itself is also deallocated.
- *******************************************************************************)
-
- PROCEDURE DisposeDialogItems (aDialog: DialogPtr);
-
-
- IMPLEMENTATION
-
- USES
- Resources
- ,TextUtils
- ,Fonts
-
- (* Application *)
- ,UEmergMem
- ;
-
-
- (*******************************************************************************
- * Types
- *******************************************************************************)
-
- TYPE
- TextStRec = PACKED RECORD
- fontIndex: Byte; {Index into STR# rsrc of font name for text}
- statStyle: Style; {Style of static text}
- statSize: Byte; {Point size of static text}
- statJust: SignedByte; {Justification of static text}
- END;
-
- DITLTmplRec = PACKED RECORD
- pad0: TextStRec; {Text style for static text items}
- displayRect: Rect; {Rect in which to display item in wind coords}
- itemType: Byte; {Type of item}
- dataLen: Byte; {Length of item data}
- CASE Integer OF
- 0: (itemRes: Integer);
- 1: (itemText: PACKED ARRAY [0..239] OF Char)
- END;
- DITLTmplPtr = ^DITLTmplRec;
-
- ItemRec = RECORD
- displayRect: Rect; {Display item rect in window coords}
- refCon: LongInt; {Used for anything client wants}
- dismissor: Boolean; {True if the item is a dismissor}
- CASE itemType: Integer OF {Code for item type or 0 if last item}
- 0: (itemControl: ControlHandle); {Handle to item control}
- 1: (itemText: Handle; {Handle to text of static text}
- itemTypeInfo: TypeInfoRec) {Type info for static text}
- END;
- ItemListArr = ARRAY [0..255] OF ItemRec;
- ItemListPtr = ^ItemListArr;
- ItemListHnd = ^ItemListPtr;
-
-
- {$S DialogUtils}
- (*******************************************************************************
- * Public: InstallDialogItems
- *
- * This routine is mainly a DITL-resource interpreter. After loading the DITL
- * resource with a resource ID passed in itemListNum into memory, it reads the
- * information in it to build up an array of dialog items in an ItemListArr,
- * which is defined in the TYPE section of this source file. This routine
- * allocates the item array and attaches it to the "items" field of the specified
- * DialogRecord. Once the item array is filled, the DITL is no longer needed and
- * is made purgeable.
- *
- * Currently, this routine handles push buttons and static text fields. Push
- * buttons are simply handled by calling NewControl. The resulting ControlHandle
- * is placed into the itemControl field of the ItemRec. For static text items,
- * a handle to the text is placed into itemText and the style information is
- * placed into the itemTypeInfo.
- *
- * Static text items are handled a little differently, and involves a change to
- * the DITL structure. I’ve kept the size of the DITL the same as it ever was,
- * but the four bytes that are described as a “placeholder for handle or
- * procedure pointer” on page 427 of Inside Macintosh I are now interpreted by
- * InstallDialogItems to hold font information for static text items. This font
- * information has the structure described by TextStRec which is declared in the
- * TYPE section of this source file. This is a four-byte record that holds the
- * type face, type style, type size, and justification (really alignment) of the
- * static text item. InstallDialogItems converts this into a TypeInfoRec
- * (declared in the UDialogUtils.p file) which is then placed into the item
- * array. When DrawDialogItems is called, it draws static text items using this
- * font information.
- *
- * The TextStRec consists of four bytes. The first bytes specifies the type
- * face to use for the static text. It doesn’t specify the font number because
- * font numbers for a particular type face can vary from system to system.
- * Instead, this field holds an index into a STR# resource which holds a list of
- * font names. The STR# resource must have a resource ID equal to the resource
- * ID of the DITL being read, that is, "itemListNum."
- *
- * The second byte specifies the style that the static text is meant to be drawn
- * in. It holds the same value as the Style type. The Style type is 16 bits
- * wide, so I declared this field as a Byte instead. The third byte specifies
- * the size of text to use. Of course, being a byte, it’s limited to a point
- * size of 255 points. I didn’t think that’d be much of a problem, and you can
- * always draw the text yourself if you needed something larger. The last byte
- * specifies the alignment of text in the static text item rectangle. This field
- * can have the values teFlushRight, teFlushLeft, teFlushDefault, and teCenter.
- *
- * I wanted to keep the DITL mechanism so that Rez and particularly ResEdit could
- * still be used to edit the DITL, even though the Dialog Manager isn’t being
- * used with these kinds of dialogs. Unfortunately, I had to redefine the Rez
- * DITL template so that it could take the static text font information, and
- * worse, ResEdit won’t edit DITLs that have non-zero values in the location that
- * I’m reading the font information. So, keeping the DITL isn’t any particular
- * advantage over defining a completely new structure. But, I’ll leave it this
- * ways for now. There ARE other resource editors that might not be quite so
- * quick to criticize my DITLs.
- *
- * If all the dialog items were installed correctly, then noErr is returned. If
- * any error happend, then the operating system result code is returned and the
- * dialog item list is disposed of, leaving aDialog unaffected.
- *******************************************************************************)
-
- FUNCTION InstallDialogItems (aDialog: DialogPtr;
- itemListNum: Integer): OSErr;
-
- TYPE
- IntPtr = ^Integer;
-
- VAR
- numItems: Integer; {Number of items in item list}
- itemNum: Integer; {Item number of item we’re installing}
- itemKind: Integer; {Type of the item}
- fontNumber: Integer; {Font number of static text item}
- ditlItemPtr: DITLTmplPtr; {Pointer to each item}
- ditlList: Handle; {Handle to DITL resource}
- itemList: ItemListHnd; {Handle to the item list}
- aControl: ControlHandle; {Handle to a control we’re installing}
- aString: Str255; {String used for a couple of things}
- staticText: Handle; {Handle to text for static text item}
- dataLen: Integer; {Length of item data, rounded up to even}
- doesDismiss: Boolean; {True if the item is a dismissor}
-
- PROCEDURE RecoverError (error: Integer);
-
- BEGIN
- IF ditlList <> NIL THEN
- BEGIN
- HUnlock (ditlList);
- HPurge (ditlList)
- END;
- IF itemList <> NIL THEN
- DisposeDialogItems (aDialog);
- DialogPeek(aDialog)^.items := NIL;
- InstallDialogItems := error;
- EXIT (InstallDialogItems)
- END;
-
- BEGIN
- ditlList := NIL;
- itemList := NIL;
-
- (* Grab the requested DITL resource *)
- ditlList := GetResource ('DITL', itemListNum);
- IF ditlList = NIL THEN
- IF ResError = noErr THEN
- RecoverError (resNotFound)
- ELSE
- RecoverError (ResError);
-
- (* Make sure we don’t lose it while we’re reading from it *)
- HNoPurge (ditlList);
-
- (* Allocate item list; add 1 for flag record and 1 for numItems-1 adj *)
- numItems := IntPtr(ditlList^)^;
- itemList := ItemListHnd(NewHandleMargin (SIZEOF (ItemRec) * (numItems +
- 2), kAllocApp, NOT kAllocClr));
- IF itemList = NIL THEN
- RecoverError (memFullErr);
-
- (* Fill with kNoItem items in case of error while building item list *)
- FOR itemNum := 0 TO numItems + 1 DO
- itemList^^ [itemNum].itemType := kNoItem;
-
- (* Put the item list into the dialog record *)
- DialogPeek(aDialog)^.items := Handle(itemList);
-
- (* Point at the first item in the DITL *)
- HLock (ditlList);
- ditlItemPtr := DITLTmplPtr(ORD4(ditlList^) + SIZEOF (Integer));
-
- (* For each item in DITL, install into item list *)
- FOR itemNum := 0 TO numItems DO
- BEGIN
- (* Get the type of the item *)
- itemKind := ditlItemPtr^.itemType;
-
- (* If itemDisable flag clear, item is a dismissor *)
- IF itemKind < 128 THEN
- doesDismiss := TRUE
- ELSE
- BEGIN
- doesDismiss := FALSE;
- itemKind := itemKind - 128
- END;
-
- (* Grab the item information *)
- IF itemKind = ctrlItem + btnCtrl THEN
- BEGIN
- (* Copy control’s title to controlTitle *)
- BlockMoveData (@ditlItemPtr^.dataLen, @aString, ditlItemPtr^.
- dataLen + 1);
-
- (* Create the new control *)
- aControl := NewControl (aDialog, ditlItemPtr^.displayRect,
- aString, TRUE, 0, 0, 0, pushButProc, 0);
-
- (* Put the control’s handle into our item list *)
- itemList^^ [itemNum].itemType := itemKind;
- itemList^^ [itemNum].itemControl := aControl;
-
- (* Bail if there’s not enough memory *)
- IF FailLowMemory (0) THEN
- RecoverError (memFullErr)
- ELSE IF aControl = NIL THEN
- IF (ResError = noErr) | (ResError = resNotFound) THEN
- RecoverError (resNotFound)
- ELSE
- RecoverError (ResError);
-
- (* Put the control’s item number into the control’s refCon *)
- SetControlReference (aControl, itemNum)
- END
- ELSE IF itemKind = statText THEN
- BEGIN
- (* Allocate space for text *)
- staticText := NewHandleMargin (ditlItemPtr^.dataLen,
- kAllocApp, NOT kAllocClr);
-
- (* Put the control’s handle into our item list *)
- itemList^^ [itemNum].itemType := itemKind;
- itemList^^ [itemNum].itemText := staticText;
-
- (* Bail if there’s not enough memory for the text *)
- IF staticText = NIL THEN
- RecoverError (memFullErr);
-
- (* Copy DITL text to our text handle *)
- BlockMoveData (@ditlItemPtr^.itemText, staticText^, ditlItemPtr^.
- dataLen);
-
- (* Put a handle to the text into our item list *)
- aString [0] := CHR (0);
- IF ditlItemPtr^.pad0.fontIndex > 0 THEN
- BEGIN
- GetIndString ((*<*)aString, itemListNum, ditlItemPtr^.
- pad0.fontIndex);
- IF aString [0] = CHR (0) THEN
- GetIndString ((*<*)aString, 0, ditlItemPtr^.pad0.
- fontIndex)
- END;
- IF aString [0] = CHR (0) THEN
- fontNumber := 0
- ELSE
- GetFNum (aString, (*<*)fontNumber);
- itemList^^ [itemNum].itemTypeInfo.typeFace := fontNumber;
- itemList^^ [itemNum].itemTypeInfo.typeSize := ditlItemPtr^.
- pad0.statSize;
- itemList^^ [itemNum].itemTypeInfo.textJust := ditlItemPtr^.
- pad0.statJust;
- itemList^^ [itemNum].itemTypeInfo.typeStyle :=
- ditlItemPtr^.pad0.statStyle
- END
- ELSE
- itemList^^ [itemNum].itemType := itemKind;
-
- (* Copy interesting characteristics to our item list *)
- WITH itemList^^ [itemNum] DO
- BEGIN
- (*WITH*)displayRect := ditlItemPtr^.displayRect;
- (*WITH*)refCon := 0;
- (*WITH*)dismissor := doesDismiss
- END;
-
- (* Bump the pointer to the next item in the DITL *)
- dataLen := BAnd (ditlItemPtr^.dataLen + 1, $FFFE);
- ditlItemPtr := DITLTmplPtr(ORD4(@ditlItemPtr^.itemText) + dataLen)
- END;
-
- (* Don’t need the dialog item list any more *)
- HUnlock (ditlList);
- HPurge (ditlList);
- END;
-
-
- {$S DialogUtils}
- (*******************************************************************************
- * Public: SetStatTextItem
- *
- * The text of a static text item is specified by a handle to the text, so that
- * handle is resized to the new text length, if needed, and then the text is
- * simply BlockMoved in.
- *******************************************************************************)
-
- PROCEDURE SetStatTextItem (aDialog: DialogPtr;
- itemNum: Integer;
- textPtr: Ptr;
- textLength: Integer);
-
- VAR
- itemList: ItemListHnd; {Handle to item list}
- textHandle: Handle; {Handle to the existing item text}
-
- BEGIN
- (* Grab the item list from the dialog window’s refCon *)
- itemList := ItemListHnd(DialogPeek(aDialog)^.items);
-
- (* If the item is indeed a static text item, then set it *)
- IF itemList^^ [itemNum].itemType = statText THEN
- BEGIN
- textHandle := itemList^^ [itemNum].itemText;
- IF NOT FailLowMemory (textLength) THEN
- BEGIN
- IF GetHandleSize (textHandle) <> textLength THEN
- SetHandleSize (textHandle, textLength);
- BlockMoveData (textPtr, textHandle^, textLength)
- END
- END
- END;
-
-
- {$S DialogUtils}
- (*******************************************************************************
- * Public: GetStatTextFontInfo
- *
- * Font information for a static text item is simply stored in its itemTypeInfo
- * field. It’s a simple matter of copying this record into "typeInfo".
- *******************************************************************************)
-
- PROCEDURE GetStatTextFontInfo (aDialog: DialogPtr;
- itemNum: Integer;
- VAR typeInfo: TypeInfoRec);
-
- VAR
- itemList: ItemListHnd; {Handle to item list}
-
- BEGIN
- (* Grab the item list from the dialog window’s refCon *)
- itemList := ItemListHnd(DialogPeek(aDialog)^.items);
-
- (* If the item is indeed a static text item, then set it *)
- IF itemList^^ [itemNum].itemType = statText THEN
- typeInfo := itemList ^^ [itemNum].itemTypeInfo
- END;
-
-
- {$S DialogUtils}
- (*******************************************************************************
- * Public: DrawDialogItems
- *
- * The item list of a dialog box is stored in the "items" field of the
- * DialogRecord. This routine loops through every dialog item and draws whatever
- * item types it understands. Currently, this is static text items and icons.
- *******************************************************************************)
-
- PROCEDURE DrawDialogItems (aDialog: DialogPtr);
-
- VAR
- itemNum: Integer; {Item number of item we’re installing}
- itemList: ItemListHnd; {Handle to the item list}
- itemRect: Rect; {Rectangle of dialog item}
- staticText: Handle; {Handle to static text}
-
- BEGIN
- (* Draw any static text items or icon items in the item list*)
- itemList := ItemListHnd(DialogPeek(aDialog)^.items);
- itemNum := 0;
- WHILE itemList^^ [itemNum].itemType <> kNoItem DO
- BEGIN
- IF itemList^^ [itemNum].itemType = statText THEN
- BEGIN
- (* Item is a static text item; call TETextBox if there’s text *)
- staticText := itemList^^ [itemNum].itemText;
- IF GetHandleSize (staticText) > 0 THEN
- BEGIN
- TextFont (itemList^^ [itemNum].itemTypeInfo.typeFace);
- TextSize (itemList^^ [itemNum].itemTypeInfo.typeSize);
- TextFace (itemList^^ [itemNum].itemTypeInfo.typeStyle);
- itemRect := itemList^^ [itemNum].displayRect;
- HLock (staticText);
- TETextBox (staticText^, GetHandleSize (staticText),
- itemRect, itemList^^ [itemNum].itemTypeInfo.
- textJust);
- HUnlock (statictext)
- END
- END;
- itemNum := itemNum + 1
- END
- END;
-
-
- {$S DialogUtils}
- (*******************************************************************************
- * Public: GetDialogItemRect
- *
- * The item list of a dialog box is in the "items" field of the DialogRecord.
- * This handle is retrieved and the displayRect of the specified item into
- * "itemRect".
- *******************************************************************************)
-
- PROCEDURE GetDialogItemRect (aDialog: DialogPtr;
- itemNum: Integer;
- VAR itemRect: Rect);
-
- VAR
- itemList: ItemListHnd; {Handle to item list}
-
- BEGIN
- (* Grab the item list from the dialog window’s refCon *)
- itemList := ItemListHnd(DialogPeek(aDialog)^.items);
-
- (* Copy the item’s display rectangle *)
- itemRect := itemList^^ [itemNum].displayRect
- END;
-
-
- {$S DialogUtils}
- (*******************************************************************************
- * Public: DisposeDialogItems
- *
- * A handle to the dialog box’s dialog item list is retrieved from the
- * DialogRecord’s "items" handle. The type of each item is checked, and the
- * memory taken by that item is disposed of appropriately.
- *******************************************************************************)
-
- PROCEDURE DisposeDialogItems (aDialog: DialogPtr);
-
- VAR
- itemNum: Integer; {Item number of item we’re installing}
- itemList: ItemListHnd; {Handle to the item list}
-
- BEGIN
- (* Grab the item list from the dialog window’s refCon *)
- itemList := ItemListHnd(DialogPeek(aDialog)^.items);
-
- (* Starting at item 1, go through entire list and dispose of each item *)
- IF itemList <> NIL THEN
- BEGIN
- itemNum := 0;
- WHILE itemList^^ [itemNum].itemType <> kNoItem DO
- BEGIN
- WITH itemList^^ [itemNum] DO
- BEGIN
- IF (*WITH*)itemType = ctrlItem + btnCtrl THEN
- BEGIN
- IF (*WITH*)itemControl <> NIL THEN
- DisposeControl ((*WITH*)itemControl)
- END
- ELSE IF (*WITH*)itemType = statText THEN
- BEGIN
- IF (*WITH*)itemText <> NIL THEN
- DisposeHandle ((*WITH*)itemText)
- END
- END;
-
- (* Go on to the next item in the item list *)
- itemNum := itemNum + 1
- END;
- DisposeHandle (Handle(itemList))
- END
- END;
-
- END.
-